/*******************************************************************************
 * @file bsp_adc.c
 * @brief  ADC driver
 *
 * @version 1.0.0
 *******************************************************************************
 * @license Refer License or other description Docs
 * @author  Felix
 ******************************************************************************/

/****
Include Files
****/
#include "cpu/bsp_adc.h"
#include "sysctrl.h"
#include "gpio.h"
#include "adc.h"
#include "cpu/bsp_clock.h"

/****
Local Macros
****/

/****
Local Variables
****/


/****
Global Functions
****/

/**
 * @brief ADC mode initialization
 */
void BSP_ADC_Enable(const BSP_ADC_TypeDef *ptr)
{
    M0P_SYSCTRL->PERI_CLKEN_f.ADC = 1;
    M0P_ADC->CR0 = 0;
    M0P_ADC->CR1 = 0;

    /* enable BGR */
    M0P_BGR->CR_f.BGR_EN = 1;
    /* enable ADC */
    M0P_ADC->CR0_f.EN  = 1;
    /* delay > 20us */
    BSP_ClockdelayUs(30);

    if(AdcMskRefVolSelInBgr1p5 == ptr->ref || AdcMskRefVolSelInBgr2p5 == ptr->ref){
         /* internel 1.5V ref ro 2.5V ref */
        M0P_ADC->CR0_f.INREFEN = 1;
    }

    /* 12 ADC clock */
    /* DIV8 PCLK = 24M/8 */
    M0P_ADC->CR0 |= (uint32_t)AdcMskClkDiv8         |
                    (uint32_t)ptr->ref              |
                    (uint32_t)AdcMskBufDisable      |
                    (uint32_t)AdcMskSampCycle12Clk;
    //if(ptr->single){
        M0P_ADC->CR1_f.MODE = AdcSglMode;
    //} else {
    //    M0P_ADC->CR1_f.MODE = AdcScanMode;
    //}

    return;
}

void BSP_ADC_Disable(const BSP_ADC_TypeDef *ptr)
{
	 M0P_BGR->CR_f.BGR_EN = 0;
	 M0P_ADC->CR0 = 0;
	 M0P_ADC->CR1 = 0;
     M0P_SYSCTRL->PERI_CLKEN_f.ADC = 0;
}

uint32_t BSP_ADC_Sample(const BSP_ADC_IDX adcIdx, uint8_t ch)
{
    uint32_t temp = 0;
    uint8_t i;
    stc_gpio_cfg_t gpioCfg;
    en_gpio_port_t gpio;
    en_gpio_pin_t pin;

    DDL_ZERO_STRUCT(gpioCfg);
    gpioCfg.enDir = GpioDirIn;
    gpioCfg.enPu = GpioPuDisable;
    gpioCfg.enPd = GpioPdDisable;

    /* PA0~PA7 */
    if(ch < 8){
        gpio = GpioPortA;
        pin = (en_gpio_pin_t)ch;
    }
    /* PB0~PB1 */
    else if(8 <= ch && ch <= 9){
        gpio = GpioPortB;
        pin = (en_gpio_pin_t)(ch - 8);
    }
    /* PC0~PC5 */
    else if(10 <= ch && ch <= 15){
        gpio = GpioPortC;
        pin = (en_gpio_pin_t)(ch - 10);
    }
    /* PB2 */
    else if(16 == ch){
        gpio = GpioPortB;
        pin = GpioPin2;
    }
    /* PC10~PC15 */
    else if(17 <= ch && ch <= 22){
        gpio = GpioPortC;
        pin = (en_gpio_pin_t)(ch - 7);
    } else if(23 == ch){
        gpio = GpioPortC;
        pin = GpioPin6;
    }
    else if(26 < ch && ch < 30){
        M0P_ADC->CR0_f.BUF = 1;
    } else {
        return 0;
    }

    if(ch <= 23){
        Gpio_Init(gpio, pin, &gpioCfg);
        Gpio_SetAnalogMode(gpio, pin);
    }

    M0P_ADC->CR0_f.SGLMUX = ch;
    for(i = 0; i < 8; i++){
        M0P_ADC->ICR = 0;
        M0P_ADC->SGLSTART = 1;
        //while(0 == M0P_ADC->IFR_f.SGLIF);
        //M0P_ADC->ICR_f.SGLIC = 0;
        while(M0P_ADC->SGLSTART);
        temp = temp + M0P_ADC->RESULT;
    }

    temp = temp >> 3;

    return temp;
}
